/**
 * userModel.js - 用户模型
 * 
 * 这个模块定义了用户数据模型，使用Sequelize ORM映射到数据库表。
 * 它包含用户的基本信息、角色和身份验证相关字段。
 */

const { DataTypes } = require('sequelize');
const { sequelize } = require('../config/database');
const bcrypt = require('bcryptjs');

/**
 * @swagger
 * components:
 *   schemas:
 *     User:
 *       type: object
 *       required:
 *         - id
 *         - username
 *         - email
 *       properties:
 *         id:
 *           type: string
 *           format: uuid
 *           description: 用户唯一标识符
 *         username:
 *           type: string
 *           description: 用户名
 *         email:
 *           type: string
 *           format: email
 *           description: 电子邮件地址
 *         role:
 *           type: string
 *           enum: [user, admin]
 *           description: 用户角色
 *         createdAt:
 *           type: string
 *           format: date-time
 *           description: 创建时间
 *         updatedAt:
 *           type: string
 *           format: date-time
 *           description: 更新时间
 *       example:
 *         id: "1"
 *         username: "johndoe"
 *         email: "john@example.com"
 *         role: "user"
 *         createdAt: "2023-01-01T00:00:00.000Z"
 *         updatedAt: "2023-01-01T00:00:00.000Z"
 */

/**
 * 用户模型定义
 * 
 * 使用Sequelize定义用户表结构
 */
const User = sequelize.define('User', {
  // 用户ID，主键
  id: {
    type: DataTypes.UUID,
    defaultValue: DataTypes.UUIDV4,
    primaryKey: true,
    comment: '用户唯一标识符',
  },
  // 用户名
  username: {
    type: DataTypes.STRING(50),
    allowNull: false,
    unique: true,
    validate: {
      len: [3, 50],
    },
    comment: '用户名，唯一，长度3-50',
  },
  // 电子邮件
  email: {
    type: DataTypes.STRING(100),
    allowNull: false,
    unique: true,
    validate: {
      isEmail: true,
    },
    comment: '电子邮件地址，唯一',
  },
  // 密码（加密存储）
  password: {
    type: DataTypes.STRING,
    allowNull: false,
    comment: '用户密码（加密存储）',
  },
  // 用户角色
  role: {
    type: DataTypes.ENUM('user', 'admin'),
    defaultValue: 'user',
    allowNull: false,
    comment: '用户角色：普通用户或管理员',
  },
  // 最后登录时间
  lastLogin: {
    type: DataTypes.DATE,
    allowNull: true,
    comment: '最后登录时间',
  },
  // 账户状态
  status: {
    type: DataTypes.ENUM('active', 'inactive', 'suspended'),
    defaultValue: 'active',
    allowNull: false,
    comment: '账户状态：活跃、非活跃或已暂停',
  },
  // 刷新令牌
  refreshToken: {
    type: DataTypes.STRING,
    allowNull: true,
    comment: '用于刷新访问令牌的刷新令牌',
  },
}, {
  // 表名
  tableName: 'users',
  // 时间戳
  timestamps: true,
  // 钩子
  hooks: {
    // 创建用户前加密密码
    beforeCreate: async (user) => {
      if (user.password) {
        const salt = await bcrypt.genSalt(10);
        user.password = await bcrypt.hash(user.password, salt);
      }
    },
    // 更新用户前加密密码（如果密码已更改）
    beforeUpdate: async (user) => {
      if (user.changed('password')) {
        const salt = await bcrypt.genSalt(10);
        user.password = await bcrypt.hash(user.password, salt);
      }
    },
  },
});

/**
 * 验证密码
 * 
 * 比较提供的密码与存储的加密密码
 * @param {string} password - 要验证的明文密码
 * @returns {Promise<boolean>} - 如果密码匹配则返回true，否则返回false
 */
User.prototype.validatePassword = async function(password) {
  return bcrypt.compare(password, this.password);
};

/**
 * 初始化用户表
 * 
 * 创建表并添加初始管理员用户（如果不存在）
 */
const initUserTable = async () => {
  try {
    // 同步表结构
    await User.sync();
    
    // 检查是否存在管理员用户
    const adminExists = await User.findOne({
      where: {
        role: 'admin',
      },
    });
    
    // 如果不存在管理员用户，则创建一个
    if (!adminExists) {
      await User.create({
        username: 'admin',
        email: 'admin@example.com',
        password: 'admin123', // 密码会通过钩子自动加密
        role: 'admin',
      });
      console.log('已创建初始管理员用户');
    }
  } catch (error) {
    console.error('初始化用户表失败:', error);
  }
};

module.exports = {
  User,
  initUserTable,
};